package com.childenglish.config;

import com.childenglish.utils.R;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.stream.Collectors;

@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * HTML转义工具方法
     * 防止XSS攻击，转义错误消息中的特殊字符
     */
    private String escapeHtml(String input) {
        if (input == null) {
            return null;
        }
        return input
            .replace("&", "&amp;")
            .replace("<", "&lt;")
            .replace(">", "&gt;")
            .replace("\"", "&quot;")
            .replace("'", "&#x27;")
            .replace("/", "&#x2F;");
    }

    /**
     * 转义错误消息，移除用户输入的敏感信息
     */
    private String sanitizeErrorMessage(String message) {
        if (message == null) {
            return null;
        }
        // 转义HTML
        message = escapeHtml(message);
        // 移除rejected value中的用户输入（防止XSS反射）
        message = message.replaceAll("rejected value \\[.*?\\]", "rejected value [已过滤]");
        return message;
    }

    /**
     * 处理HTTP方法不支持异常
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public R<Object> handleHttpRequestMethodNotSupportedException(
            HttpRequestMethodNotSupportedException e, 
            HttpServletRequest request) {
        String method = e.getMethod();
        String[] supportedMethods = e.getSupportedMethods();
        String requestURI = request.getRequestURI();
        
        System.err.println("========================================");
        System.err.println("HTTP方法不支持异常:");
        System.err.println("请求URI: " + requestURI);
        System.err.println("请求方法: " + method);
        System.err.println("支持的方法: " + (supportedMethods != null ? String.join(", ", supportedMethods) : "无"));
        System.err.println("========================================");
        
        String supportedMethodsStr = supportedMethods != null && supportedMethods.length > 0 
            ? String.join(", ", supportedMethods) 
            : "无";
        
        return R.error(String.format(
            "请求方法 '%s' 不支持。端点 '%s' 仅支持以下方法: %s", 
            method, requestURI, supportedMethodsStr
        ));
    }

    /**
     * 处理参数验证异常（@Valid注解）
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R<Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        String errorMessage = e.getBindingResult().getFieldErrors().stream()
            .map(error -> {
                String field = error.getField();
                String message = error.getDefaultMessage();
                // 不返回rejected value，防止XSS反射
                return field + ": " + message;
            })
            .collect(Collectors.joining("; "));
        
        // 转义错误消息
        errorMessage = sanitizeErrorMessage(errorMessage);
        
        return R.error("参数验证失败: " + errorMessage);
    }

    /**
     * 处理绑定异常（表单数据绑定）
     */
    @ExceptionHandler(BindException.class)
    public R<Object> handleBindException(BindException e) {
        String errorMessage = e.getFieldErrors().stream()
            .map(error -> {
                String field = error.getField();
                String message = error.getDefaultMessage();
                // 不返回rejected value，防止XSS反射
                return field + ": " + message;
            })
            .collect(Collectors.joining("; "));
        
        // 转义错误消息
        errorMessage = sanitizeErrorMessage(errorMessage);
        
        return R.error("参数验证失败: " + errorMessage);
    }

    /**
     * 处理所有异常
     */
    @ExceptionHandler(Exception.class)
    public R<Object> handleException(Exception e) {
        e.printStackTrace();
        String message = e.getMessage();
        // 转义错误消息，防止XSS
        message = sanitizeErrorMessage(message);
        return R.error("系统错误: " + message);
    }

    /**
     * 处理空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    public R<Object> handleNullPointerException(NullPointerException e) {
        return R.error("数据不存在");
    }

    /**
     * 处理运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public R<Object> handleRuntimeException(RuntimeException e) {
        String message = e.getMessage();
        // 转义错误消息，防止XSS
        message = sanitizeErrorMessage(message);
        return R.error("操作失败: " + message);
    }
}